\documentclass{report}

\usepackage[french]{babel}
\usepackage[utf8]{inputenc}
\usepackage{amsmath}
%\usepackage{mathtools}
\usepackage{amsfonts}
\usepackage{amssymb}
\usepackage{graphicx}
\usepackage{vmargin}
\usepackage{listings}
\usepackage{color}
\usepackage{url}
\usepackage[colorlinks=true]{hyperref}
\hypersetup{urlcolor=blue,linkcolor=black,citecolor=black,colorlinks=true}
\usepackage{float}
\usepackage{listingsutf8}
\usepackage{titlesec}

\urlstyle{sf}

\lstset{
	tabsize=4,
        basicstyle=\scriptsize,
        aboveskip={1.5\baselineskip},
        columns=fixed,
        showstringspaces=false,
        extendedchars=true,
        breaklines=true,
        prebreak = \raisebox{0ex}[0ex][0ex]{\ensuremath{\hookleftarrow}},
	frame=single,
        showtabs=false,
        showspaces=false,
        showstringspaces=false,
        identifierstyle=\ttfamily,
        keywordstyle=\color[rgb]{0,0,1},
        commentstyle=\color[rgb]{0.133,0.545,0.133},
        stringstyle=\color[rgb]{0.627,0.126,0.941},
	language=C,
	inputencoding=utf8/latin1
}

\titleformat{\chapter}[hang]{\bf\huge}{\thechapter}{2pc}{}

\begin{document}
     \begin{figure}[h]
                \begin{center}
                        \title	{Informatique 2\up{ème} année \\
	                        \textbf {\LARGE{Projet Réseau}} \\
				Rapport final
				}

                        \author{Sylvain \bsc{Bilange} \and Alexis \bsc{Ferriere} \and Jérôme \bsc{Boé} \and David \bsc{Cardoso}}
                        \maketitle
                        \null
                        \null
                        \null
                        \null
                        \null
                        \null
                        \null
                        \null
                        \null
                        \null
                        \null
                        \null
                        \null
                       	\includegraphics[scale=0.2]{pictures/logo_enseirb.png}\\
                        ENSEIRB-MATMECA\\
                        1 Avenue du docteur Albert Schweitzer \\
                        33402 Talence\\
                \end{center}
        \end{figure}



	\setcounter{page}{0}

	\thispagestyle{empty}

	\clearpage

	%\tableofcontents

	\clearpage

	\chapter{Introduction}
		Le but de ce projet est de développer une application de partage de fichiers pair-à-pair. Ce genre d'application est déjà largement répandu dans le paysage informatique, mais il existe deux variantes~:~des versions centralisées (de type Napster) et des versions distribuées (de type eDonkey). \\
		Nous allons être amenés lors de ce projet à implémenter ces deux versions. Nous aurons donc à implémenter un tracker (nécessaire à la version centralisée) ainsi qu'un client, coeur de l'application pair à pair. Une des contraintes qui nous étaient imposées était d'utiliser à la fois le langage C et le langage Java, nous avons choisi d'implémenter le tracker en C et le client en Java, puisque nous avons estimé qu'il valait mieux se servir des outils plus poussés du Java pour alléger le travail à effectuer sur le client (a priori plus long à coder). \\
		Nous n'en sommes actuellement qu'à la version centralisée, dont nous allons vous présenter l'implémentation dans ce rapport.

	\chapter{Tracker}

		Le rôle du tracker est central puisqu'il est un intermédiaire entre les différents pairs. Ainsi, chaque client doit se signaler auprès du tracker pour pouvoir être connu des autres clients, et indique les fichiers qu'il est en train de télécharger (leech) et ceux -complets- qu'il laisse à disposition. \\
		Les requêtes auxquelles le tracker doit être capable de répondre sont les suivantes~:
		~\\
		\begin{itemize}
			\item	{\footnotesize \textsf{announce listen \$Port seed [\$Filename1 \$Length1 \$PieceSize1 \$Key1…] leech [\$Key3 \$Key4 …]}} \\
			a pour rôle d'initier la connexion entre le pair et le tracker.
			~\\

			\item  	{\footnotesize \textsf{look [\$Criterion1 \$Criterion2 …]}} \\
			 donne une vue des fichiers disponibles sur l'ensemble du réseau. Les critères peuvent porter sur différents éléments (nom, taille...)
			~\\

			\item {\footnotesize \textsf{getfile \$Key}} \\
			permet au client de connaître le (ou les) propriétaire(s), grâce à l'adresse IP et au numéro de port d'un fichier.
			~\\

			\item {\footnotesize \textsf{update seed [\$Key1 \$Key2 \$Key3 …] leech [\$Key10 \$Key11 \$Key12 …]}} \\
			met à jour les différents fichiers liés à un pair.
			~\\

		\end{itemize}

		Nous allons maintenant vous détailler quel système nous avons mis en place pour pouvoir traiter ces différents cas.

		\section{organisation et modules}

		    Comme tous les travaux en équipes, nous avons découpé notre code au maximum, de façon à être le plus propre et modulaire possible pour
		    garantir la possibilité de travailler à plusieurs dessus sans conflits ni difficultés de compréhension.\\
		    C'est pourquoi nous avons 4 modules ainsi qu'un main se devant d'être le plus concis possible~:\\
		    \\
		    \textbf{daemon} : Correspond au main de notre projet, il se contente d'initialiser une connexion TCP pour permettre à des clients de se connecter.
		    Ces fonctions d'initialisation, c'est-à-dire la gestion des sockets et des structures correspondantes sont dans le module \textbf{network} de façon
		    à ne pas polluer le main de fonctions propres au réseau et de découper le code.\\
		    Ce main initialise aussi une "base de donnée" qui est en réalité notre module \textbf{database} permettant d'enregistrer les différents fichiers reliés
		    aux différents pairs, qui seront obtenus lors des requêtes transmises par les clients (pairs).\\
		    Suite à ces initialisations, ce main permet d'écouter en continu toute nouvelle connexion d'un éventuel client, suite à quoi il lance un thread par client.
		    Ce thread dédié au client permettra de traiter l'ensemble des requêtes à satisfaire, pour laisser le main libre à toute autre nouvelle connexion.\\
		    \\
		    \textbf{network} : Ce module regroupe donc toutes les fonctions de programmation réseau liées aux sockets de façon, par exemple, à abstraire l'utilisation
		    des sockets quelque peu verbeuse et complexe, pour fournir à l'utilisateur et aux autres modules des fonctions plus concises. Ces fonctions permettent de
		    créer des sockets et donc une connexion TCP bi-directionnelle basée sur l'IPv4 en lui associant un port d'écoute, de façon à communiquer avec le client qui
		    procède de la même manière.\\
		    \\
		    \textbf{process} : Ce module regroupe 5 fonctions, 4 étant destinées à parser les 4 types de requêtes que le tracker doit pouvoir recevoir (détaillés plus bas)
		    et une autre destinée à réceptionner les différentes requêtes clientes écrites dans le socket, et donc, en fonction de la requête, appeler une des 4 autres
		    fonctions correspondantes au type de requête à traiter. Cette fonction est donc celle appelée lors de la création du thread dans daemon.c (main).\\
		    Elle lit donc dans une boucle infinie la socket de manière bloquante. Dès qu'une requête est reçue elle l'aiguille vers le traitement correspondant.
		    Pour chaque requête créée une trace de la nouvelle version de la base de donnée est affichée.\\

                    En ce qui concerne la fin de connexion, que nous n'arrivions pas à détecter, nous avons récolu le problème grace à la fonction recv, qui renvoie 0

                    lorsque le pair a effectué un arrêt normal. Quand c'est le cas, on ferme le socket et on indique que le client s'est déconnecté.
		    \\
            Finalement, lorsqu'on envoie une réponse au client, on ajoute en fin un "$\backslash n$", puisqu'il semble évident pour le client
            (codé en java) d'utiliser la méthode $readline$, qui lit une ligne. Or une ligne est caractérisée par un $\backslash n$.
            Si ce délimiteur n'est pas présent dans le cahier des charges, il permet de simplifier le code du client,
            et surtout d'éviter des erreurs supplémentaires, d'autant que ce n'est pas difficile à ajouter dans le tracker.
		    \\


		    \textbf{database} : Ce module se comporte comme une base de données. Il possède une structure rassemblant pour chaque pair les fichiers correspondants.
		    C'est à partir de ces enregistrements que l'on pourra connaître les différents fichiers présents sur le réseau et donc répondre aux différents clients.
		    On y retrouve donc des fonctions d'initialisation de structures peer et file, puis d'insertion de ces dernières dans la structure database
		    ou alors de suppression. \\
		    Puis il y a des fonctions plus élaborées comme des recherches de fichiers par clé ou des recherches de pairs par IP.\\
		    \\
		    \textbf{request} :  Ce module rassemble plusieurs fonctions annexes de traitement, traitements beaucoup sollicités par le module process.
		    On y trouve donc des fonctions pour gérer des chaînes de caractères correspondant à la syntaxe des requêtes de notre projet. ainsi que des traitements
		    relatifs aux requêtes look, getfile, ...\\
		    \\

		\section{structure de données}

            La base de donnée utilise donc une variable globale de facon à ce que tous les différents threads correspondants aux différentes connexions clientes puissent
            y accéder. Ainsi qu'une variable verrou qui permet de verrouiller l'accès à la base de données quand il y a une écriture en cours sur celle-ci.\\
            La structure de cette BDD est donc une liste de pairs contenant eux-mêmes une liste de fichiers~:

            \begin{lstlisting}
struct database *db;
pthread_mutex_t m_db;

struct database {
	struct peer **list_peer;
	int nb_peer;
};

struct peer {
	char *ip;
	char *port;
	struct file **list_file;
	int nb_file;
};

struct file {
	char *name;
	char *size;
	char *block_size;
	char *key;
	int is_seed;
};

            \end{lstlisting}

            La structure du module network a été créée pour que l'on puisse sauvegarder l'addresse IP en plus de la socket cliente
            lors des différentes fonctions d'initialisation de la socket. Car l'addresse IP n'est récupérable que lors de l'initialisation de la connexion
            et doit être passée au thread pour que la base de données puisse être correctement renseignée~:

            \begin{lstlisting}
struct ip_and_socket {
	int sockfd;
	char *ip;
};
            \end{lstlisting}

            D'autres structures sont utilisées mais correspondent à des requêtes précises, elles seront donc abordées plus bas.


        \section{traitement des requêtes}

		    \subsection{announce}

		        Cette fonction prend donc la requête en paramètre et sait que c'est une requête de type announce, car garanti par la
		        fonction d'aiguillage (process\_request).\\
		        On parse donc cette requête en commençant par découper cette chaîne de caractère pour chaque caractère espace.
		        Ceci nous permet donc pour chaque mot de savoir si la requête est correcte, si elle ne l'est pas on annule le traitement et on l'indique au client.
		        Ceci nous permet de faire une vérification au fur et à mesure. On crée ensuite des structures fichier pour chaque élément présent dans la
		        requête. Puis lorsque le parsing est fini on verrouille l'accès à la base de données (mutex) pour y ajouter ces nouveaux fichiers. Si le client était déjà
		        présent dans la base de données on écrase alors les précédents fichiers qu'il avait déclarés.

		    \subsection{look}
		        Nous avons distingué deux cas pour cette reqûete : \\
		        \begin{itemize}
		           \item Le cas vide {\footnotesize \textsf{look []}} \\
			         qui donne une vue générale des fichiers, c'est en effet le seul moyen d'avoir une vue d'ensemble.\\
			         Nous avons estimé que c'était la solution la plus cohérente.\\
			       \item Le cas courant {\footnotesize \textsf{look [\$Criterion1 \$Criterion2 …]}} \\
			         qui permet de filtrer les résultats selon un certain nombre de critères. \\
			         Nous avons dû mettre en place une structure supplémentaire, la structure criterion suivante~:
			         \begin{lstlisting}
struct criterion {
	char * entity;
	char comp;
	char * value;

	struct criterion * next;
};
                    \end{lstlisting}

                     Le champ $entity$ désigne la nature de l'objet comparé (nom des fichiers et leur taille dans notre cas),
                     $comp$ est la nature de la comparaison ('$<$','$=$' ou '$>$') et $value$ la valeur avec laquelle il faut comparer.\\
			         Nous la remplissons en parsant la requête (et donc les différents critères), puis nous
			         la réutilisons en parcourant la base de données (pour trouver d'éventuelles correspondances et remplir la réponse au client).
		        \end{itemize}

                        Nous avons corrigé le problème que l'on avait au milieu du projet, qui était que l'on ne pouvait pas faire de requête après un look.
                        Cela était dû à un realloc (que l'on utilisait pour compléter la réponse à renvoyer). En le remplaçant par un malloc ``classique'' tout
                        fonctionnait sans problème, et nous avons découvert par la suite que l'utilisation répétée de realloc était déconseillée.

		    \subsection{getfile}
                Cette requête est relativement simple étant donnée notre structure de données.
                Il suffit en effet de parcourir l'ensemble des pairs et leur fichiers, comparer les clefs
                et éventuellement ajouter adresse IP et port à la réponse.
                Le fonctionnement sous-jacent est identique à celui des fonctions précédentes.

		    \subsection{update}
                Le principe de notre fonction est simple : \\
                Nous identifions le pair qui fait la requête grâce à son adresse IP, puis nous créons un pair temporaire
                que nous remplissons en parsant -toujours de la même manière- la requête. La construction du peer se fait exactement
                comme dans la fonction qui traite la requête $announce$.\\
                Bien sûr, nous veillons à la fin à supprimer le pair d'origine et à le remplacer par le pair créé au début de la fonction.
                ~\\
                Un point important est que nous avons considéré qu'un pair ne pouvait seeder qu'un fichier qui était déjà seed,
                ou qui était leech (ce qui signifie que son téléchargement est terminé), mais un fichier ne peut pas devenir seed
                s'il était auparavant absent de la base. En revanche, n'importe quel fichier peut être déclaré en leech
                lors d'un update.


		\section{tests}

            Nous avons également créé un client en C, de facon à tester notre programme mais aussi à dégrossir les erreurs qui pourraient être obtenues
            par le client Java. ce programme envoie au tracker une succession de requêtes écrites en dur dans le programme et se contente de comparer
            la réponse obtenue avec celle qui doit être obtenue. C'est un mécanisme de test avec assertions. Il nous permet de garantir que lors d'implémentations
            de nouvelles fonctionnalités coté serveur il n'y a pas de régression du code et que les précédentes requêtes passent toujours. Il garantie aussi la robustesse
            et la rapidité/efficacité.

		\section{Gestion des erreurs}

            Nous n'avons pas mis en place de gestion des erreurs, ainsi si une requête incorrecte est invoquée, une message d'erreur
            s'affichera côté serveur mais pas côté client : on suppose que le client ne fait pas d'erreur, ou en tous cas est conscient
            de celles qu'il commet.
            Malheureusement, certains problèmes demeurent, que ce soit du point de vue du fonctionnement propre du
            tracker ou du point de vue de la compatibilité entre le client et notre tracker. Les problèmes sont les suivants :

	\chapter{Client}
		\input{client.tex}

	\chapter{Conclusion}
        Ce projet nous permet de nous initier à la programmation réseau et de ce fait il est très intéressant. Nous avons l'occasion de nous familiariser, à la fois en C et en JAVA, avec la manipulation des sockets et d'échanges de données. La communication entre un client JAVA et un tracker C nous a posé cependant de nombreux problèmes, notamment au niveau du formatage des requêtes et de l'échange de chaines de caractères. Nous avons résolu ces différents problèmes en nous adaptant aux langages qui nous étaient proposés, ce qui constitue une satisfaction.\\
        Pour aller plus loin, nous aurions pu nous intéresser à la gestion réelle des téléchargements, quelles pièces sélectionner, optimiser la vitesse de téléchargement, etc. Finalement, nous regrettons de ne pas nous être penchés sur la version distribuée, qui est l'étape supérieure à réaliser.
\end{document}

